{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mesh to Mesh Registration Example\n",
    "\n",
    "ITK natively supports image-to-image registration, which is a common operation for medical images with symmetry. Another common method of storing 3D volumetric data is to represent volume surfaces as meshes. One way to get surface features from a sample mesh is to register a common atlas of correspondences and find related points on the surface of the sample mesh. In this example we seek to register two meshes using various ITK metrics and optimization techniques.\n",
    "\n",
    "Registration classes are defined in the Python `hasi` submodule and built on top of the ITK Python wrapping. The `MeanSquaresRegistrar` and `DiffeoRegistrar` classes apply registration techniques to images derived from mesh inputs, while the `PointSetEntropyRegistrar` aims to register meshes via point set entropy metrics. Mesh registration is carried out with each class in this notebook on sample bone femur mesh data downloaded to the `examples/Data` folder."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook requires the following modules, which can be either acquired via `pip` or built alongside the ITK `master` branch:\n",
    "- [ITK](https://github.com/InsightSoftwareConsortium/ITK/)\n",
    "- [ITKBoneEnhancement](https://github.com/InsightSoftwareConsortium/ITKBoneEnhancement)\n",
    "- [ITKMeshToPolyData](https://github.com/InsightSoftwareConsortium/ITKMeshToPolyData)\n",
    "- [ITKWidgets](https://github.com/InsightSoftwareConsortium/itkwidgets)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "!{sys.executable} -m pip install itk itkwidgets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Update sys.path to reference src/ modules\n",
    "import os\n",
    "import copy\n",
    "import importlib\n",
    "from urllib.request import urlretrieve\n",
    "\n",
    "import itk\n",
    "from itkwidgets import view, checkerboard, compare\n",
    "from ipywidgets import FloatProgress, Label, HBox, VBox, FloatText, ColorPicker, Button\n",
    "PATTERN_COUNT = 5\n",
    "\n",
    "module_path = os.path.abspath(os.path.join('..'))\n",
    "\n",
    "if module_path not in sys.path:\n",
    "    sys.path.append(module_path)\n",
    "    \n",
    "# Ignore wrapping warnings from itkwidgets\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.makedirs('Input', exist_ok=True)\n",
    "os.makedirs('Output', exist_ok=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "MESH_TO_USE = '901-R'\n",
    "TARGET_MESH_FILE = f'Input/{MESH_TO_USE}-mesh.vtk'\n",
    "TEMPLATE_MESH_FILE = f'Input/906-R-atlas.obj'\n",
    "\n",
    "MEANSQUARES_OUTPUT_FILE = f'Output/{MESH_TO_USE}-meansquares-registered.obj'\n",
    "DIFFEO_OUTPUT_FILE = f'Output/{MESH_TO_USE}-diffeo-registered.obj'\n",
    "POINTSET_OUTPUT_FILE = f'Output/{MESH_TO_USE}-pointset-registered.obj'\n",
    "POINTSET_RESAMPLED_OUTPUT_FILE = f'Output/{MESH_TO_USE}-pointset-resampled.obj'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Download meshes\n",
    "if not os.path.exists(TARGET_MESH_FILE):\n",
    "    url = 'https://data.kitware.com/api/v1/file/5f9daaba50a41e3d1924dae9/download'\n",
    "    urlretrieve(url, TARGET_MESH_FILE)\n",
    "if not os.path.exists(TEMPLATE_MESH_FILE):\n",
    "    url = 'https://data.kitware.com/api/v1/file/608b006d2fa25629b970f139/download'\n",
    "    urlretrieve(url, TEMPLATE_MESH_FILE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "template_mesh = itk.meshread(TEMPLATE_MESH_FILE, itk.F)\n",
    "target_mesh = itk.meshread(TARGET_MESH_FILE, itk.F)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Compare geometries with ITKWidgets\n",
    "\n",
    "We can use `view`, `compare`, and `checkerboard` to inspect mesh and image data. Comparing the two meshes, we see that they are generally similar but do not precisely align by default. Attempting to set sample correspondences from the template mesh with this default alignment would yield a poor description of the sample surface. Registration will align the surfaces so that the two bones better coincide."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3f97be0e263e437d8e479ea4c06bc1c9",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Viewer(geometries=[{'vtkClass': 'vtkPolyData', 'points': {'vtkClass': 'vtkPoints', 'numberOfComponents': 3, 'd…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "view(geometries=[template_mesh,target_mesh])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Mesh-To-Image Conversion\n",
    "\n",
    "The `hasi` package provides Python functions for various stages of the HASI shape analysis pipeline in its `align` module. These include static methods for creating surface meshes from sample images, deforming an atlas to a sample, iteratively refining an atlas from a population, and more.\n",
    "\n",
    "The `align.mesh_to_image` function takes in a set of 3D meshes and outputs a set of ITK 3D images describing the meshes in a common space. The spacing, origin, and size of the images may be derived from the minimum common bounding box of the mesh or set from a reference image. The final space of the meshes is generated with a small empty buffer around the sample representation (5% in each direction)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from src.hasi.hasi.align import mesh_to_image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "target_image, template_image = mesh_to_image([target_mesh, template_mesh])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "86c55950b93f460ea8de289690969607",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "AppLayout(children=(HBox(children=(Label(value='Link:'), Checkbox(value=False, description='cmap'), Checkbox(v…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "compare(template_image,target_image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "95b94e1d51ad4b7ebe414a9a8d135fe7",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(Viewer(annotations=False, interpolation=False, rendered_image=<itk.itkImagePython.itkImageF3; p…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "checkerboard(template_image, target_image, pattern=PATTERN_COUNT)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run Mean Squares Image Registration\n",
    "\n",
    "The `MeanSquaresRegistrar` class converts meshes to images and runs [Broyden-Fletcher-Goldfarb-Shanno Optimization](https://itk.org/Doxygen/html/classitk_1_1LBFGSBOptimizerv4.html) on a [BSplineTransform](https://itk.org/Doxygen/html/classitk_1_1BSplineTransform.html) to iteratively reduce the mean square error. The resulting transform is then applied to resample the target mesh into the template mesh domain.\n",
    "\n",
    "Progress is shown with an itkwidgets display via hooks into the ITK event-observer system. The resultant mesh is returned as an object in the Python environment and may be optionally written out to a file. Iteration updates may also be printed to the output window with the optional `verbose` flag."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "from src.hasi.hasi.meansquaresregistrar import MeanSquaresRegistrar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Must instantiate a registration object to initialize optimizers\n",
    "registrar = MeanSquaresRegistrar(verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ee07b15bc88043c5ad7b95868ea154d5",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(Label(value='Register images'), FloatProgress(value=0.0, max=21.0)))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "progress = FloatProgress(\n",
    "        min=0.0,\n",
    "        max=21.0,\n",
    "        step=1\n",
    "    )\n",
    "box = HBox([\n",
    "    Label('Register images'),\n",
    "    progress\n",
    "])\n",
    "box"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def update_progress():\n",
    "    progress.value = registrar.optimizer.GetCurrentIteration()\n",
    "registrar.optimizer.AddObserver(itk.IterationEvent(), update_progress)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 0 Metric: 0.4953344442828443 Infinity Norm: 0.0\n",
      "Iteration: 0 Metric: 0.3679928041625301 Infinity Norm: 0.0\n",
      "Iteration: 0 Metric: 0.3679928041625301 Infinity Norm: 0.0\n",
      "Iteration: 1 Metric: 0.1382597111142386 Infinity Norm: 0.002047170989457994\n",
      "Iteration: 1 Metric: 0.1382597111142386 Infinity Norm: 0.002047170989457994\n",
      "Iteration: 2 Metric: 0.09620259423214085 Infinity Norm: 0.001261876484024073\n",
      "Iteration: 2 Metric: 0.09620259423214085 Infinity Norm: 0.001261876484024073\n",
      "Iteration: 3 Metric: 0.0810644365222312 Infinity Norm: 0.0011402423999786182\n",
      "Iteration: 3 Metric: 0.0810644365222312 Infinity Norm: 0.0011402423999786182\n",
      "Iteration: 4 Metric: 0.05506265821062781 Infinity Norm: 0.0008026746053761812\n",
      "Iteration: 4 Metric: 0.05506265821062781 Infinity Norm: 0.0008026746053761812\n",
      "Iteration: 5 Metric: 0.036229100368238225 Infinity Norm: 0.0005999657307756083\n",
      "Iteration: 5 Metric: 0.036229100368238225 Infinity Norm: 0.0005999657307756083\n",
      "Iteration: 6 Metric: 0.02201122948495042 Infinity Norm: 0.0006569240263049952\n",
      "Iteration: 6 Metric: 0.02201122948495042 Infinity Norm: 0.0006569240263049952\n",
      "Iteration: 7 Metric: 0.019790912974060545 Infinity Norm: 0.000227595005185355\n",
      "Iteration: 7 Metric: 0.019790912974060545 Infinity Norm: 0.000227595005185355\n",
      "Iteration: 8 Metric: 0.017138213201441897 Infinity Norm: 0.00012848767601378967\n",
      "Iteration: 8 Metric: 0.017138213201441897 Infinity Norm: 0.00012848767601378967\n",
      "Iteration: 9 Metric: 0.01643926158089219 Infinity Norm: 0.00011380109594120822\n",
      "Iteration: 9 Metric: 0.01643926158089219 Infinity Norm: 0.00011380109594120822\n",
      "Iteration: 10 Metric: 0.015742424102559768 Infinity Norm: 0.000229305332514829\n",
      "Iteration: 10 Metric: 0.015742424102559768 Infinity Norm: 0.000229305332514829\n",
      "Iteration: 11 Metric: 0.015332139820951112 Infinity Norm: 9.86042590450415e-05\n",
      "Iteration: 11 Metric: 0.015332139820951112 Infinity Norm: 9.86042590450415e-05\n",
      "Iteration: 12 Metric: 0.014893029866989713 Infinity Norm: 9.041142269583126e-05\n",
      "Iteration: 12 Metric: 0.014893029866989713 Infinity Norm: 9.041142269583126e-05\n",
      "Iteration: 13 Metric: 0.014155799479607961 Infinity Norm: 8.750465542941682e-05\n",
      "Iteration: 13 Metric: 0.014155799479607961 Infinity Norm: 8.750465542941682e-05\n",
      "Iteration: 14 Metric: 0.013727488501522448 Infinity Norm: 8.1341387937945e-05\n",
      "Iteration: 14 Metric: 0.013727488501522448 Infinity Norm: 8.1341387937945e-05\n",
      "Iteration: 15 Metric: 0.013269794609552825 Infinity Norm: 0.00015860022289330145\n",
      "Iteration: 15 Metric: 0.013269794609552825 Infinity Norm: 0.00015860022289330145\n",
      "Iteration: 16 Metric: 0.013082032206910437 Infinity Norm: 0.00010944034907393472\n",
      "Iteration: 16 Metric: 0.013082032206910437 Infinity Norm: 0.00010944034907393472\n",
      "Iteration: 17 Metric: 0.01251044810222833 Infinity Norm: 8.291646063426698e-05\n",
      "Iteration: 17 Metric: 0.01251044810222833 Infinity Norm: 8.291646063426698e-05\n",
      "Iteration: 18 Metric: 0.01216931779260898 Infinity Norm: 9.827412298789554e-05\n",
      "Iteration: 18 Metric: 0.01216931779260898 Infinity Norm: 9.827412298789554e-05\n",
      "Iteration: 19 Metric: 0.011936519135127685 Infinity Norm: 5.2764813925673704e-05\n",
      "Iteration: 19 Metric: 0.011936519135127685 Infinity Norm: 5.2764813925673704e-05\n",
      "Iteration: 20 Metric: 0.011692025245038271 Infinity Norm: 9.881889798097749e-05\n",
      "Iteration: 20 Metric: 0.011692025245038271 Infinity Norm: 9.881889798097749e-05\n",
      "Iteration: 21 Metric: 0.011584744320551963 Infinity Norm: 3.0638833099466936e-05\n",
      "Iteration: 21 Metric: 0.011584744320551963 Infinity Norm: 3.0638833099466936e-05\n"
     ]
    }
   ],
   "source": [
    "(transform_result, mesh_result) = registrar.register(template_mesh,\n",
    "                                                     target_mesh,\n",
    "                                                     num_iterations=200,\n",
    "                                                     convergence_factor=5e11,\n",
    "                                                     gradient_convergence_tolerance=1e-35)\n",
    "itk.meshwrite(mesh_result, MEANSQUARES_OUTPUT_FILE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Comparison of the resulting mesh with the target shows successful registration. The template image is deformed with B-splines to approximate the shape of the target image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b60fe94ac1d0403cbcc5b9e13528bce2",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Viewer(geometries=[{'vtkClass': 'vtkPolyData', 'points': {'vtkClass': 'vtkPoints', 'numberOfComponents': 3, 'd…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "view(geometries=[mesh_result,target_mesh])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Diffeomorphic Registration\n",
    "\n",
    "The `DiffeoRegistrar` class converts meshes to images and performs registration using the [Diffeomorphic Demons registration algorithm](https://itk.org/Doxygen/html/classitk_1_1DiffeomorphicDemonsRegistrationFilter.html). The resultant deformation field is then applied to resample the target mesh into the template mesh domain.\n",
    "\n",
    "Custom observers may print out iteration data accessed via the `registrar.filter` object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "from src.hasi.hasi.diffeoregistrar import DiffeoRegistrar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "registrar = DiffeoRegistrar(verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b1bb3874dbb44eea8d67736c7b614fdc",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(Label(value='Register images'), FloatProgress(value=0.0, max=200.0)))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "diffeoProgress = FloatProgress(\n",
    "        min=0.0,\n",
    "        max=200.0,\n",
    "        step=1\n",
    "    )\n",
    "diffeoBox = HBox([\n",
    "    Label('Register images'),\n",
    "    diffeoProgress\n",
    "])\n",
    "diffeoBox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def update_diff_progress():\n",
    "    diffeoProgress.value = registrar.filter.GetElapsedIterations()\n",
    "\n",
    "registrar.filter.AddObserver(itk.IterationEvent(),update_diff_progress)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 0 Metric: 1.7976931348623157e+308 RMS Change: 1.7976931348623157e+308\n",
      "Iteration: 1 Metric: 0.49533444450275316 RMS Change: 0.013359611954732018\n",
      "Iteration: 2 Metric: 0.49199781461519565 RMS Change: 0.013039523388312891\n",
      "Iteration: 3 Metric: 0.490142503758756 RMS Change: 0.012588951149819737\n",
      "Iteration: 4 Metric: 0.48831526156735333 RMS Change: 0.012125892645666197\n",
      "Iteration: 5 Metric: 0.4876264321046579 RMS Change: 0.0117265151362644\n",
      "Iteration: 6 Metric: 0.48637588753497457 RMS Change: 0.011475353166185287\n",
      "Iteration: 7 Metric: 0.4848329850901018 RMS Change: 0.011286081549756901\n",
      "Iteration: 8 Metric: 0.48323803744259636 RMS Change: 0.01110896155680142\n",
      "Iteration: 9 Metric: 0.4816613820019586 RMS Change: 0.010905596244263766\n",
      "Iteration: 10 Metric: 0.4799231170176491 RMS Change: 0.010695953163007688\n",
      "Iteration: 11 Metric: 0.47819615858812137 RMS Change: 0.010497861548657563\n",
      "Iteration: 12 Metric: 0.47641801587190835 RMS Change: 0.01032998778603012\n",
      "Iteration: 13 Metric: 0.47463753255757624 RMS Change: 0.010193145157335156\n",
      "Iteration: 14 Metric: 0.4725753735317666 RMS Change: 0.010085778528113432\n",
      "Iteration: 15 Metric: 0.4705445610719899 RMS Change: 0.009983062101354839\n",
      "Iteration: 16 Metric: 0.46835314467361183 RMS Change: 0.009870206391886458\n",
      "Iteration: 17 Metric: 0.4661931707221723 RMS Change: 0.009734936839479302\n",
      "Iteration: 18 Metric: 0.4638398448774739 RMS Change: 0.009610781030472214\n",
      "Iteration: 19 Metric: 0.4617263143098048 RMS Change: 0.009517145154083553\n",
      "Iteration: 20 Metric: 0.4596308870966816 RMS Change: 0.00943975534109862\n",
      "Iteration: 21 Metric: 0.45765992990626214 RMS Change: 0.009356962692324744\n",
      "Iteration: 22 Metric: 0.45564904932109535 RMS Change: 0.009255841179589937\n",
      "Iteration: 23 Metric: 0.454054939409943 RMS Change: 0.009126666058239186\n",
      "Iteration: 24 Metric: 0.45265670419313525 RMS Change: 0.008996198569406281\n",
      "Iteration: 25 Metric: 0.45126435618474847 RMS Change: 0.008874723883875012\n",
      "Iteration: 26 Metric: 0.44997859707814153 RMS Change: 0.00875590057998006\n",
      "Iteration: 27 Metric: 0.44868278305493836 RMS Change: 0.008652919645094055\n",
      "Iteration: 28 Metric: 0.4475157724666354 RMS Change: 0.00855390234257343\n",
      "Iteration: 29 Metric: 0.44628145441325595 RMS Change: 0.008471322866461394\n",
      "Iteration: 30 Metric: 0.4450578744943134 RMS Change: 0.00839418271893196\n",
      "Iteration: 31 Metric: 0.44381953437328964 RMS Change: 0.008326982533882693\n",
      "Iteration: 32 Metric: 0.44258775461957356 RMS Change: 0.008263291458922541\n",
      "Iteration: 33 Metric: 0.44133959396962213 RMS Change: 0.00820518135823613\n",
      "Iteration: 34 Metric: 0.4401098214527868 RMS Change: 0.00814792258899901\n",
      "Iteration: 35 Metric: 0.4388818595160368 RMS Change: 0.008095010513203316\n",
      "Iteration: 36 Metric: 0.43749092474381784 RMS Change: 0.008043100444020878\n",
      "Iteration: 37 Metric: 0.43564875311473567 RMS Change: 0.008001337488979209\n",
      "Iteration: 38 Metric: 0.43370194230716685 RMS Change: 0.007956409132000538\n",
      "Iteration: 39 Metric: 0.4311092442088367 RMS Change: 0.00791950022909736\n",
      "Iteration: 40 Metric: 0.42852416074334043 RMS Change: 0.007883946134578351\n",
      "Iteration: 41 Metric: 0.4258208137675556 RMS Change: 0.007852169469502637\n",
      "Iteration: 42 Metric: 0.4231977163312322 RMS Change: 0.007819974800232004\n",
      "Iteration: 43 Metric: 0.4205323448942154 RMS Change: 0.00779192034075132\n",
      "Iteration: 44 Metric: 0.417693843056047 RMS Change: 0.007764015569610969\n",
      "Iteration: 45 Metric: 0.41429447935831465 RMS Change: 0.007736153265900176\n",
      "Iteration: 46 Metric: 0.41051505791476683 RMS Change: 0.007714538044809252\n",
      "Iteration: 47 Metric: 0.4078069432083755 RMS Change: 0.0076905269636213785\n",
      "Iteration: 48 Metric: 0.4054533839896938 RMS Change: 0.007667410831468288\n",
      "Iteration: 49 Metric: 0.40319366514658117 RMS Change: 0.007642652354453806\n",
      "Iteration: 50 Metric: 0.4008872988176601 RMS Change: 0.007620560144435727\n",
      "Iteration: 51 Metric: 0.39861609265140036 RMS Change: 0.00759407021548737\n",
      "Iteration: 52 Metric: 0.3962473989727755 RMS Change: 0.007565579062730043\n",
      "Iteration: 53 Metric: 0.393744494261409 RMS Change: 0.007547903159101403\n",
      "Iteration: 54 Metric: 0.39142684097183883 RMS Change: 0.007519902689929017\n",
      "Iteration: 55 Metric: 0.3888736380851286 RMS Change: 0.00750755034967287\n",
      "Iteration: 56 Metric: 0.386471047959163 RMS Change: 0.007487763411360683\n",
      "Iteration: 57 Metric: 0.3838115395510912 RMS Change: 0.007480174592254754\n",
      "Iteration: 58 Metric: 0.38191067148527236 RMS Change: 0.0074620476547658495\n",
      "Iteration: 59 Metric: 0.38005191392866544 RMS Change: 0.007454257338282007\n",
      "Iteration: 60 Metric: 0.3784059964338122 RMS Change: 0.007438790696220938\n",
      "Iteration: 61 Metric: 0.3767361061953015 RMS Change: 0.0074334690962882905\n",
      "Iteration: 62 Metric: 0.37520073799037557 RMS Change: 0.007421140719749772\n",
      "Iteration: 63 Metric: 0.3736390135166056 RMS Change: 0.007415608772603905\n",
      "Iteration: 64 Metric: 0.37224199228563565 RMS Change: 0.007406645011065641\n",
      "Iteration: 65 Metric: 0.37082835433844225 RMS Change: 0.0074024389262657125\n",
      "Iteration: 66 Metric: 0.36955409393095806 RMS Change: 0.007393899812572415\n",
      "Iteration: 67 Metric: 0.3682049220957266 RMS Change: 0.0073889599515244144\n",
      "Iteration: 68 Metric: 0.36693894773573643 RMS Change: 0.007380716190409424\n",
      "Iteration: 69 Metric: 0.36563207568944156 RMS Change: 0.007377744756573956\n",
      "Iteration: 70 Metric: 0.3643753329917615 RMS Change: 0.007368622974328965\n",
      "Iteration: 71 Metric: 0.3630994428566003 RMS Change: 0.0073664913082269546\n",
      "Iteration: 72 Metric: 0.36186181569646453 RMS Change: 0.007360136650111157\n",
      "Iteration: 73 Metric: 0.36058982853399046 RMS Change: 0.007355494354055072\n",
      "Iteration: 74 Metric: 0.3593911320087199 RMS Change: 0.007349169935406191\n",
      "Iteration: 75 Metric: 0.3581493381455749 RMS Change: 0.00734580746173212\n",
      "Iteration: 76 Metric: 0.3569643393856591 RMS Change: 0.007339786094847547\n",
      "Iteration: 77 Metric: 0.35572616825340947 RMS Change: 0.007336228444958939\n",
      "Iteration: 78 Metric: 0.3545850773672667 RMS Change: 0.007329007156496724\n",
      "Iteration: 79 Metric: 0.3533477608371418 RMS Change: 0.0073273335956979555\n",
      "Iteration: 80 Metric: 0.3522046830793003 RMS Change: 0.007321508484029454\n",
      "Iteration: 81 Metric: 0.35097789295882786 RMS Change: 0.007321327495913644\n",
      "Iteration: 82 Metric: 0.3498223422266538 RMS Change: 0.007314152272226366\n",
      "Iteration: 83 Metric: 0.348636249224488 RMS Change: 0.007313151598658787\n",
      "Iteration: 84 Metric: 0.34748682321573315 RMS Change: 0.0073077353339975485\n",
      "Iteration: 85 Metric: 0.3462540591739775 RMS Change: 0.0073097556480534835\n",
      "Iteration: 86 Metric: 0.34516383896791164 RMS Change: 0.007302037085969709\n",
      "Iteration: 87 Metric: 0.34390766216059593 RMS Change: 0.007302791925778989\n",
      "Iteration: 88 Metric: 0.34277981765802756 RMS Change: 0.007297662825029363\n",
      "Iteration: 89 Metric: 0.3415568382974554 RMS Change: 0.007299129737522346\n",
      "Iteration: 90 Metric: 0.34044678126808625 RMS Change: 0.007292092179718334\n",
      "Iteration: 91 Metric: 0.3392237698626274 RMS Change: 0.007293723018239292\n",
      "Iteration: 92 Metric: 0.33806360068684266 RMS Change: 0.007286576763981694\n",
      "Iteration: 93 Metric: 0.3368715299954688 RMS Change: 0.0072887990149214064\n",
      "Iteration: 94 Metric: 0.3357172110686938 RMS Change: 0.0072805999374824905\n",
      "Iteration: 95 Metric: 0.3344852728004095 RMS Change: 0.007283677210701344\n",
      "Iteration: 96 Metric: 0.3333704064675494 RMS Change: 0.007274849946512961\n",
      "Iteration: 97 Metric: 0.3321366779605496 RMS Change: 0.007279168552592468\n",
      "Iteration: 98 Metric: 0.3310525709331826 RMS Change: 0.007271092149149359\n",
      "Iteration: 99 Metric: 0.32988403768813646 RMS Change: 0.0072721416420762275\n",
      "Iteration: 100 Metric: 0.3287778154681473 RMS Change: 0.007264694378902668\n",
      "Iteration: 101 Metric: 0.32744532557938544 RMS Change: 0.007268470552590831\n",
      "Iteration: 102 Metric: 0.3261351815006039 RMS Change: 0.007259974873316029\n",
      "Iteration: 103 Metric: 0.32462848784993825 RMS Change: 0.007266212160013481\n",
      "Iteration: 104 Metric: 0.32324707171062955 RMS Change: 0.007256335621336796\n",
      "Iteration: 105 Metric: 0.32160789329570016 RMS Change: 0.007263003705962943\n",
      "Iteration: 106 Metric: 0.3201537792371009 RMS Change: 0.007256183781265089\n",
      "Iteration: 107 Metric: 0.3184817453741396 RMS Change: 0.007260544958387898\n",
      "Iteration: 108 Metric: 0.31694841527660333 RMS Change: 0.007253256742711291\n",
      "Iteration: 109 Metric: 0.3153411767661876 RMS Change: 0.00726078764121433\n",
      "Iteration: 110 Metric: 0.31389361671181426 RMS Change: 0.007250439338191659\n",
      "Iteration: 111 Metric: 0.31231257635811444 RMS Change: 0.007257080091007015\n",
      "Iteration: 112 Metric: 0.3108838655164915 RMS Change: 0.007250065474695516\n",
      "Iteration: 113 Metric: 0.30930307494294157 RMS Change: 0.007255277688424457\n",
      "Iteration: 114 Metric: 0.307927121286086 RMS Change: 0.007246969450142894\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 115 Metric: 0.3063552301301444 RMS Change: 0.0072544715577085635\n",
      "Iteration: 116 Metric: 0.30499025708048805 RMS Change: 0.007245972988814546\n",
      "Iteration: 117 Metric: 0.3034550585458994 RMS Change: 0.007252260081452726\n",
      "Iteration: 118 Metric: 0.3020681634478834 RMS Change: 0.007245775136241464\n",
      "Iteration: 119 Metric: 0.300560266296785 RMS Change: 0.007251024131039496\n",
      "Iteration: 120 Metric: 0.2991600045892858 RMS Change: 0.007245469877084949\n",
      "Iteration: 121 Metric: 0.2976003670321141 RMS Change: 0.0072504201340405396\n",
      "Iteration: 122 Metric: 0.29616745186846516 RMS Change: 0.007244353701644031\n",
      "Iteration: 123 Metric: 0.2946398147859524 RMS Change: 0.007251717901203141\n",
      "Iteration: 124 Metric: 0.2933072535015559 RMS Change: 0.00724372394648649\n",
      "Iteration: 125 Metric: 0.29182044336183477 RMS Change: 0.0072486780913258815\n",
      "Iteration: 126 Metric: 0.29041490124590047 RMS Change: 0.007244446345622724\n",
      "Iteration: 127 Metric: 0.28897342135847376 RMS Change: 0.0072489073042364596\n",
      "Iteration: 128 Metric: 0.28764615051633624 RMS Change: 0.00724311186768436\n",
      "Iteration: 129 Metric: 0.2862065581167292 RMS Change: 0.007248489786743753\n",
      "Iteration: 130 Metric: 0.2849228269730864 RMS Change: 0.0072423039047224535\n",
      "Iteration: 131 Metric: 0.2835670785736472 RMS Change: 0.007248034538782019\n",
      "Iteration: 132 Metric: 0.2822305427119003 RMS Change: 0.007241422486828033\n",
      "Iteration: 133 Metric: 0.2808409706670168 RMS Change: 0.007245928110497088\n",
      "Iteration: 134 Metric: 0.27958668772338224 RMS Change: 0.007241495645726199\n",
      "Iteration: 135 Metric: 0.2783665618031045 RMS Change: 0.007246621585775773\n",
      "Iteration: 136 Metric: 0.27713435621034765 RMS Change: 0.0072405601334853955\n",
      "Iteration: 137 Metric: 0.2758338705378451 RMS Change: 0.0072460555433496165\n",
      "Iteration: 138 Metric: 0.27469682517344385 RMS Change: 0.0072417365679518335\n",
      "Iteration: 139 Metric: 0.2734203666547468 RMS Change: 0.007246275438769506\n",
      "Iteration: 140 Metric: 0.2722488605373728 RMS Change: 0.007242423534036323\n",
      "Iteration: 141 Metric: 0.2710364525647318 RMS Change: 0.0072463668332993945\n",
      "Iteration: 142 Metric: 0.2698826819333694 RMS Change: 0.007242148091993577\n",
      "Iteration: 143 Metric: 0.26869302864587397 RMS Change: 0.007247880995653785\n",
      "Iteration: 144 Metric: 0.2675167968669246 RMS Change: 0.007242380647410754\n",
      "Iteration: 145 Metric: 0.26630565929678796 RMS Change: 0.007247958419038936\n",
      "Iteration: 146 Metric: 0.26519967914669834 RMS Change: 0.007243560014650869\n",
      "Iteration: 147 Metric: 0.2639680091206827 RMS Change: 0.007250029067387411\n",
      "Iteration: 148 Metric: 0.26287482400160367 RMS Change: 0.007243974196379681\n",
      "Iteration: 149 Metric: 0.2617141640038354 RMS Change: 0.0072501575885044935\n",
      "Iteration: 150 Metric: 0.26058676758318333 RMS Change: 0.007246694083768997\n",
      "Iteration: 151 Metric: 0.2594228787630591 RMS Change: 0.007251387190224789\n",
      "Iteration: 152 Metric: 0.2583679813529645 RMS Change: 0.007246892136425043\n",
      "Iteration: 153 Metric: 0.2571654980851679 RMS Change: 0.007253300955870309\n",
      "Iteration: 154 Metric: 0.2560586166869107 RMS Change: 0.007248910563806883\n",
      "Iteration: 155 Metric: 0.2549233683909337 RMS Change: 0.007254724513138397\n",
      "Iteration: 156 Metric: 0.25384179907127813 RMS Change: 0.007250019454147409\n",
      "Iteration: 157 Metric: 0.25262253857496036 RMS Change: 0.007256465370614507\n",
      "Iteration: 158 Metric: 0.25159123352841334 RMS Change: 0.007251530703712058\n",
      "Iteration: 159 Metric: 0.25040812314896677 RMS Change: 0.007258887011597403\n",
      "Iteration: 160 Metric: 0.24932287213260088 RMS Change: 0.007253096121812245\n",
      "Iteration: 161 Metric: 0.24817321725862043 RMS Change: 0.007258907475157261\n",
      "Iteration: 162 Metric: 0.24713188460405375 RMS Change: 0.007255392376622654\n",
      "Iteration: 163 Metric: 0.24604618671451567 RMS Change: 0.007259534295265224\n",
      "Iteration: 164 Metric: 0.24507035916772127 RMS Change: 0.00725714967950749\n",
      "Iteration: 165 Metric: 0.24402454194468443 RMS Change: 0.007261922374269905\n",
      "Iteration: 166 Metric: 0.24306522360088842 RMS Change: 0.007258264855013469\n",
      "Iteration: 167 Metric: 0.24208588115963425 RMS Change: 0.007263033825305916\n",
      "Iteration: 168 Metric: 0.24116273576327338 RMS Change: 0.007259503395582826\n",
      "Iteration: 169 Metric: 0.24013373945037847 RMS Change: 0.007264246403620821\n",
      "Iteration: 170 Metric: 0.23909636965860864 RMS Change: 0.007260822686780239\n",
      "Iteration: 171 Metric: 0.23797010646174024 RMS Change: 0.007264678889267012\n",
      "Iteration: 172 Metric: 0.23693655406603367 RMS Change: 0.007262377817969602\n",
      "Iteration: 173 Metric: 0.2358273707371063 RMS Change: 0.007268168575174578\n",
      "Iteration: 174 Metric: 0.23479936586677852 RMS Change: 0.007264486981465544\n",
      "Iteration: 175 Metric: 0.2336148256142723 RMS Change: 0.007268982282392109\n",
      "Iteration: 176 Metric: 0.23254034105040913 RMS Change: 0.007268459415183134\n",
      "Iteration: 177 Metric: 0.23135991436209294 RMS Change: 0.007271204157589504\n",
      "Iteration: 178 Metric: 0.23025121783750255 RMS Change: 0.007269941802228063\n",
      "Iteration: 179 Metric: 0.22908973519363007 RMS Change: 0.0072747459457669274\n",
      "Iteration: 180 Metric: 0.22806405097716376 RMS Change: 0.007271693012734939\n",
      "Iteration: 181 Metric: 0.22696698547508024 RMS Change: 0.007277363210255257\n",
      "Iteration: 182 Metric: 0.22598519527008307 RMS Change: 0.007274013549699205\n",
      "Iteration: 183 Metric: 0.2249015310227123 RMS Change: 0.007279400809991705\n",
      "Iteration: 184 Metric: 0.22384800639162727 RMS Change: 0.007277154569733687\n",
      "Iteration: 185 Metric: 0.22277246692525712 RMS Change: 0.00728161041957055\n",
      "Iteration: 186 Metric: 0.22182365684430064 RMS Change: 0.007279387622324303\n",
      "Iteration: 187 Metric: 0.2206727118494763 RMS Change: 0.0072846793683966505\n",
      "Iteration: 188 Metric: 0.21959788470408687 RMS Change: 0.007282069619720847\n",
      "Iteration: 189 Metric: 0.2184805160824901 RMS Change: 0.007287939934177383\n",
      "Iteration: 190 Metric: 0.2174857277136334 RMS Change: 0.007285615705340575\n",
      "Iteration: 191 Metric: 0.21644791608007097 RMS Change: 0.00729017242339547\n",
      "Iteration: 192 Metric: 0.21550298025238596 RMS Change: 0.007287574340426355\n",
      "Iteration: 193 Metric: 0.21446590463692342 RMS Change: 0.0072937807406704995\n",
      "Iteration: 194 Metric: 0.21354760998075492 RMS Change: 0.00728938482645177\n",
      "Iteration: 195 Metric: 0.21246583540106467 RMS Change: 0.007295743989977221\n",
      "Iteration: 196 Metric: 0.21153082644500987 RMS Change: 0.0072931141990843044\n",
      "Iteration: 197 Metric: 0.21059702986891277 RMS Change: 0.007296182641841479\n",
      "Iteration: 198 Metric: 0.20961285299385646 RMS Change: 0.007296276942151118\n",
      "Iteration: 199 Metric: 0.20865738944815707 RMS Change: 0.007299741411534927\n",
      "Iteration: 200 Metric: 0.20779041789239788 RMS Change: 0.007297045101247399\n"
     ]
    }
   ],
   "source": [
    "(transform_result, mesh_result) = registrar.register(template_mesh,\n",
    "                                        target_mesh,\n",
    "                                        max_rms_error=1e-3,\n",
    "                                        verbose=True)\n",
    "itk.meshwrite(mesh_result, DIFFEO_OUTPUT_FILE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Comparison of the resulting mesh with the target shows successful registration. The deformation field applied to the template mesh closely matches the shape of the target."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "386baf2d46d24f5bb4fc4092340c5d0b",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Viewer(geometries=[{'vtkClass': 'vtkPolyData', 'points': {'vtkClass': 'vtkPoints', 'numberOfComponents': 3, 'd…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "view(geometries=[mesh_result, target_mesh])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Entropy-based Registration\n",
    "\n",
    "The `PointSetEntropyRegistrar` class registers two 3D meshes by computing the transform which minimizes entropy measures between the two point clouds without need for mesh-to-image conversion.\n",
    "\n",
    "In this example we substitute a [`EuclideanDistancePointSetToPointSetMetric`](https://itk.org/Doxygen/html/classitk_1_1EuclideanDistancePointSetToPointSetMetricv4.html) to compare the two clouds. By default an [`itk.AffineTransform`](https://itk.org/Doxygen/html/classitk_1_1AffineTransform.html) is employed for registration, but the user may subsitute a different transform inheriting from `itk.Transform` as an argument to registration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "from src.hasi.hasi.pointsetentropyregistrar import PointSetEntropyRegistrar\n",
    "registrar = PointSetEntropyRegistrar(verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "7cc6b765e3384e33af92b86dbbbf7efe",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(Label(value='Register images'), FloatProgress(value=0.0, max=185.0)))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "entropyProgress = FloatProgress(\n",
    "        min=0.0,\n",
    "        max=185.0,\n",
    "        step=1\n",
    "    )\n",
    "progressBox = HBox([\n",
    "    Label('Register images'),\n",
    "    entropyProgress\n",
    "])\n",
    "progressBox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def update_progress():\n",
    "    entropyProgress.value = registrar.optimizer.GetCurrentIteration()\n",
    "\n",
    "registrar.optimizer.AddObserver(itk.IterationEvent(),update_progress)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 0 Metric: 0.0\n",
      "Iteration: 0 Metric: 0.0\n",
      "Iteration: 0 Metric: 0.0\n",
      "Iteration: 0 Metric: 0.0\n",
      "Iteration: 0 Metric: 0.0\n",
      "Iteration: 0 Metric: 0.0\n",
      "Iteration: 0 Metric: 0.18402767981233376\n",
      "Iteration: 1 Metric: 0.13636549597252293\n",
      "Iteration: 2 Metric: 0.1136153451996774\n",
      "Iteration: 3 Metric: 0.10070102504901322\n",
      "Iteration: 4 Metric: 0.0921356833845075\n",
      "Iteration: 5 Metric: 0.08639007757362922\n",
      "Iteration: 6 Metric: 0.08227116489324207\n",
      "Iteration: 7 Metric: 0.07907374804042967\n",
      "Iteration: 8 Metric: 0.07637873779025549\n",
      "Iteration: 9 Metric: 0.07405272544249199\n",
      "Iteration: 10 Metric: 0.0719671439265937\n",
      "Iteration: 11 Metric: 0.07005118273844133\n",
      "Iteration: 12 Metric: 0.06828105853186942\n",
      "Iteration: 13 Metric: 0.06660776118233713\n",
      "Iteration: 14 Metric: 0.06498893467311129\n",
      "Iteration: 15 Metric: 0.06343569110339238\n",
      "Iteration: 16 Metric: 0.06194662338114907\n",
      "Iteration: 17 Metric: 0.06055190889404482\n",
      "Iteration: 18 Metric: 0.059165763253996674\n",
      "Iteration: 19 Metric: 0.05782261337640995\n",
      "Iteration: 20 Metric: 0.05652837680168472\n",
      "Iteration: 21 Metric: 0.05530507143716108\n",
      "Iteration: 22 Metric: 0.054134602834920165\n",
      "Iteration: 23 Metric: 0.053020636495240706\n",
      "Iteration: 24 Metric: 0.051944194750049855\n",
      "Iteration: 25 Metric: 0.05091371680519884\n",
      "Iteration: 26 Metric: 0.04990854226515862\n",
      "Iteration: 27 Metric: 0.048950925455557744\n",
      "Iteration: 28 Metric: 0.048024307153977146\n",
      "Iteration: 29 Metric: 0.04712948446720358\n",
      "Iteration: 30 Metric: 0.0462846441709203\n",
      "Iteration: 31 Metric: 0.04545128218920508\n",
      "Iteration: 32 Metric: 0.044643358857768024\n",
      "Iteration: 33 Metric: 0.043888957619121746\n",
      "Iteration: 34 Metric: 0.04316445250215185\n",
      "Iteration: 35 Metric: 0.04248362994983003\n",
      "Iteration: 36 Metric: 0.04183262747532614\n",
      "Iteration: 37 Metric: 0.0412037429531749\n",
      "Iteration: 38 Metric: 0.04059294224542183\n",
      "Iteration: 39 Metric: 0.040016154126255296\n",
      "Iteration: 40 Metric: 0.03945396290133864\n",
      "Iteration: 41 Metric: 0.03892002005470285\n",
      "Iteration: 42 Metric: 0.03840443107046075\n",
      "Iteration: 43 Metric: 0.03791056816607884\n",
      "Iteration: 44 Metric: 0.037459777174137766\n",
      "Iteration: 45 Metric: 0.03701969721014922\n",
      "Iteration: 46 Metric: 0.03658629120129073\n",
      "Iteration: 47 Metric: 0.036148671462410145\n",
      "Iteration: 48 Metric: 0.03571479106454752\n",
      "Iteration: 49 Metric: 0.035295001371293634\n",
      "Iteration: 50 Metric: 0.034907069624876136\n",
      "Iteration: 51 Metric: 0.03453613144565263\n",
      "Iteration: 52 Metric: 0.03417757083123989\n",
      "Iteration: 53 Metric: 0.03382311711899252\n",
      "Iteration: 54 Metric: 0.03348168950333608\n",
      "Iteration: 55 Metric: 0.03316049376927745\n",
      "Iteration: 56 Metric: 0.032854504731590364\n",
      "Iteration: 57 Metric: 0.03257361869598419\n",
      "Iteration: 58 Metric: 0.0323092692810875\n",
      "Iteration: 59 Metric: 0.03205047461546761\n",
      "Iteration: 60 Metric: 0.03179900730212333\n",
      "Iteration: 61 Metric: 0.03154807758579675\n",
      "Iteration: 62 Metric: 0.03128955525259092\n",
      "Iteration: 63 Metric: 0.031031266067091168\n",
      "Iteration: 64 Metric: 0.0307914884795602\n",
      "Iteration: 65 Metric: 0.030563173149740608\n",
      "Iteration: 66 Metric: 0.030350547461453388\n",
      "Iteration: 67 Metric: 0.030142253805310115\n",
      "Iteration: 68 Metric: 0.02994255382189799\n",
      "Iteration: 69 Metric: 0.02974295236977903\n",
      "Iteration: 70 Metric: 0.029546454083031515\n",
      "Iteration: 71 Metric: 0.029353613918214175\n",
      "Iteration: 72 Metric: 0.029176655608014523\n",
      "Iteration: 73 Metric: 0.02900495709415009\n",
      "Iteration: 74 Metric: 0.028833241261115253\n",
      "Iteration: 75 Metric: 0.02866841099200312\n",
      "Iteration: 76 Metric: 0.02851848145912843\n",
      "Iteration: 77 Metric: 0.0283712340287105\n",
      "Iteration: 78 Metric: 0.028230380322573304\n",
      "Iteration: 79 Metric: 0.028095750075436212\n",
      "Iteration: 80 Metric: 0.027961613232161852\n",
      "Iteration: 81 Metric: 0.027824980354412124\n",
      "Iteration: 82 Metric: 0.027689411876232813\n",
      "Iteration: 83 Metric: 0.027556395188551245\n",
      "Iteration: 84 Metric: 0.027428622992412974\n",
      "Iteration: 85 Metric: 0.027303406081203404\n",
      "Iteration: 86 Metric: 0.027186117232923704\n",
      "Iteration: 87 Metric: 0.027075258495759858\n",
      "Iteration: 88 Metric: 0.026965938095766064\n",
      "Iteration: 89 Metric: 0.026862171444398442\n",
      "Iteration: 90 Metric: 0.02676113508640635\n",
      "Iteration: 91 Metric: 0.026658520164617016\n",
      "Iteration: 92 Metric: 0.02655655109006952\n",
      "Iteration: 93 Metric: 0.026460628740804664\n",
      "Iteration: 94 Metric: 0.026370572332453213\n",
      "Iteration: 95 Metric: 0.02628404695256076\n",
      "Iteration: 96 Metric: 0.026201904741376496\n",
      "Iteration: 97 Metric: 0.026117630173188012\n",
      "Iteration: 98 Metric: 0.026031621135564214\n",
      "Iteration: 99 Metric: 0.025945551150562032\n",
      "Iteration: 100 Metric: 0.02586712635392992\n",
      "Iteration: 101 Metric: 0.025791748067019032\n",
      "Iteration: 102 Metric: 0.025720664700857238\n",
      "Iteration: 103 Metric: 0.025649681459085194\n",
      "Iteration: 104 Metric: 0.025575052378321538\n",
      "Iteration: 105 Metric: 0.025501953968138983\n",
      "Iteration: 106 Metric: 0.02543213911567575\n",
      "Iteration: 107 Metric: 0.0253693540814346\n",
      "Iteration: 108 Metric: 0.025310507143506158\n",
      "Iteration: 109 Metric: 0.025255749849054102\n",
      "Iteration: 110 Metric: 0.025206912561183778\n",
      "Iteration: 111 Metric: 0.02515718284278915\n",
      "Iteration: 112 Metric: 0.025107656792173236\n",
      "Iteration: 113 Metric: 0.025057741287912962\n",
      "Iteration: 114 Metric: 0.025010688978617465\n",
      "Iteration: 115 Metric: 0.024964973881096884\n",
      "Iteration: 116 Metric: 0.02491822486369632\n",
      "Iteration: 117 Metric: 0.024871389282046276\n",
      "Iteration: 118 Metric: 0.024826145186941734\n",
      "Iteration: 119 Metric: 0.024779736450485656\n",
      "Iteration: 120 Metric: 0.024733731527519724\n",
      "Iteration: 121 Metric: 0.024688514996213995\n",
      "Iteration: 122 Metric: 0.024644659156440134\n",
      "Iteration: 123 Metric: 0.024601106594520736\n",
      "Iteration: 124 Metric: 0.024559033817192162\n",
      "Iteration: 125 Metric: 0.02451921839639598\n",
      "Iteration: 126 Metric: 0.02448143950882282\n",
      "Iteration: 127 Metric: 0.024446486754136826\n",
      "Iteration: 128 Metric: 0.024413773193221765\n",
      "Iteration: 129 Metric: 0.024381921902966806\n",
      "Iteration: 130 Metric: 0.024351333496826694\n",
      "Iteration: 131 Metric: 0.02432167726832519\n",
      "Iteration: 132 Metric: 0.024292232577790777\n",
      "Iteration: 133 Metric: 0.02426293830106277\n",
      "Iteration: 134 Metric: 0.02423350002594374\n",
      "Iteration: 135 Metric: 0.02420389743056043\n",
      "Iteration: 136 Metric: 0.024173685843396894\n",
      "Iteration: 137 Metric: 0.024145668193371675\n",
      "Iteration: 138 Metric: 0.024119650869516295\n",
      "Iteration: 139 Metric: 0.024094390673283866\n",
      "Iteration: 140 Metric: 0.02407021831117784\n",
      "Iteration: 141 Metric: 0.02404671926774642\n",
      "Iteration: 142 Metric: 0.02402348568517847\n",
      "Iteration: 143 Metric: 0.02400032375702212\n",
      "Iteration: 144 Metric: 0.023978599124547646\n",
      "Iteration: 145 Metric: 0.02395686599034836\n",
      "Iteration: 146 Metric: 0.023936004803659736\n",
      "Iteration: 147 Metric: 0.02391535751448654\n",
      "Iteration: 148 Metric: 0.023896039696370868\n",
      "Iteration: 149 Metric: 0.023877271561901437\n",
      "Iteration: 150 Metric: 0.023859596760080138\n",
      "Iteration: 151 Metric: 0.023843542241006963\n",
      "Iteration: 152 Metric: 0.023829314267910733\n",
      "Iteration: 153 Metric: 0.02381631617010177\n",
      "Iteration: 154 Metric: 0.02380405611697416\n",
      "Iteration: 155 Metric: 0.023791822981691937\n",
      "Iteration: 156 Metric: 0.023780564646966897\n",
      "Iteration: 157 Metric: 0.023770233505179744\n",
      "Iteration: 158 Metric: 0.02376066053938431\n",
      "Iteration: 159 Metric: 0.023751984091467386\n",
      "Iteration: 160 Metric: 0.023745017582532793\n",
      "Iteration: 161 Metric: 0.023738465826114687\n",
      "Iteration: 162 Metric: 0.023732203575458848\n",
      "Iteration: 163 Metric: 0.023726327142139993\n",
      "Iteration: 164 Metric: 0.02372052286522561\n",
      "Iteration: 165 Metric: 0.023715209337304487\n",
      "Iteration: 166 Metric: 0.023708716031133385\n",
      "Iteration: 167 Metric: 0.023702164892591367\n",
      "Iteration: 168 Metric: 0.02369610797126128\n",
      "Iteration: 169 Metric: 0.02369003172957132\n",
      "Iteration: 170 Metric: 0.023684307632522928\n",
      "Iteration: 171 Metric: 0.023678529485915218\n",
      "Iteration: 172 Metric: 0.023672232162141038\n",
      "Iteration: 173 Metric: 0.023665952940276604\n",
      "Iteration: 174 Metric: 0.023660048099062577\n",
      "Iteration: 175 Metric: 0.023653658924159666\n",
      "Iteration: 176 Metric: 0.02364728016950504\n",
      "Iteration: 177 Metric: 0.023641139704051736\n",
      "Iteration: 178 Metric: 0.023634456561241544\n",
      "Iteration: 179 Metric: 0.02362778478883809\n",
      "Iteration: 180 Metric: 0.023622004225594594\n",
      "Iteration: 181 Metric: 0.02361640735124622\n",
      "Iteration: 182 Metric: 0.023610557208121108\n",
      "Iteration: 183 Metric: 0.023604903292065976\n",
      "Iteration: 184 Metric: 0.023599869985642317\n",
      "Iteration: 185 Metric: 0.023599869985642317\n",
      "Number of iterations run: 185\n",
      "Final metric value: 0.023599869985642317\n",
      "Final transform position: [1.0106625225070383, -0.02275704571888098, 0.12374059701277136, 0.04097965683098047, 1.0140192795610004, -0.13518422332905158, -0.11392776422934717, 0.16289349012456367, 0.9931393057995168, -0.19910442594468017, 0.04431398224202008, -0.34451813263325887]\n",
      "Optimizer scales: [11.744144658808226, 4.475390574611993, 2.5780283025156336, 11.744144658808226, 4.475390574611993, 2.5780283025156336, 11.744144658808226, 4.475390574611993, 2.5780283025156336, 1.0000000000000018, 1.0000000000000018, 1.0000000000000018]\n",
      "Optimizer learning rate: 1.0\n"
     ]
    }
   ],
   "source": [
    "metric = itk.EuclideanDistancePointSetToPointSetMetricv4[itk.PointSet[itk.F,3]].New()\n",
    "\n",
    "(transform_result, mesh_result) = registrar.register(\n",
    "                       template_mesh=template_mesh,\n",
    "                       target_mesh=target_mesh,\n",
    "                       metric=metric,\n",
    "                       learning_rate=1.0,\n",
    "                       minimum_convergence_value=1e-6,\n",
    "                       convergence_window_size=3,\n",
    "                       max_iterations=300)\n",
    "itk.meshwrite(mesh_result, POINTSET_OUTPUT_FILE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Comparison of the registered template with the target mesh shows successful registration. Note that the `itk.AffineTransform` does not change the shape of the template atlas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "1ec277e501e74e6d9c0331fb729706f0",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Viewer(geometries=[{'vtkClass': 'vtkPolyData', 'points': {'vtkClass': 'vtkPoints', 'numberOfComponents': 3, 'd…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "view(geometries=[mesh_result,target_mesh])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Resample From Target\n",
    "\n",
    "A common procedure for comparing correspondences across samples is to register an atlas to each mesh sample and then deform the template to align with points on the target surface. The `hasi` package provides an interface to use ITK's [`KdTree`](https://itk.org/Doxygen/html/classitk_1_1Statistics_1_1KdTree.html) to deform each template point to its nearest neighbor on the target mesh."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "from src.hasi.hasi.align import resample_template_from_target\n",
    "\n",
    "template_deformed = resample_template_from_target(mesh_result, target_mesh)\n",
    "\n",
    "itk.meshwrite(template_deformed,POINTSET_RESAMPLED_OUTPUT_FILE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3d172146f88a4ea3b4af6552ba8dd12a",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Viewer(geometries=[{'vtkClass': 'vtkPolyData', 'points': {'vtkClass': 'vtkPoints', 'numberOfComponents': 3, 'd…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Use the wireframe option to examine correspondences on the deformed template\n",
    "view(geometries=[template_deformed,target_mesh])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Clean up file output\n",
    "os.remove(MEANSQUARES_OUTPUT_FILE)\n",
    "os.remove(DIFFEO_OUTPUT_FILE)\n",
    "os.remove(POINTSET_OUTPUT_FILE)\n",
    "os.remove(POINTSET_RESAMPLED_OUTPUT_FILE)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
